package com.yjb.tenet.boot.system.application.manager;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yjb.tenet.boot.common.constants.GlobalConstants;
import com.yjb.tenet.boot.common.exception.CustomException;
import com.yjb.tenet.boot.common.exception.enums.ErrorCodeEnum;
import com.yjb.tenet.boot.framework.satoken.core.LoginUser;
import com.yjb.tenet.boot.framework.satoken.core.utils.SecurityFrameworkUtils;
import com.yjb.tenet.boot.system.application.checker.SysUserChecker;
import com.yjb.tenet.boot.system.application.service.SysDeptService;
import com.yjb.tenet.boot.system.application.service.SysRoleService;
import com.yjb.tenet.boot.system.application.service.SysUserRoleService;
import com.yjb.tenet.boot.system.application.service.SysUserService;
import com.yjb.tenet.boot.system.domain.dto.CheckMsg;
import com.yjb.tenet.boot.system.domain.dto.LoginUserDTO;
import com.yjb.tenet.boot.system.domain.dto.SysRolePageDTO;
import com.yjb.tenet.boot.system.domain.dto.SysUserPageDTO;
import com.yjb.tenet.boot.system.domain.entity.SysDept;
import com.yjb.tenet.boot.system.domain.entity.SysUser;
import com.yjb.tenet.boot.system.domain.entity.SysUserRole;
import com.yjb.tenet.boot.system.domain.form.MyInfoEditForm;
import com.yjb.tenet.boot.system.domain.form.SysUserAddForm;
import com.yjb.tenet.boot.system.domain.form.SysUserEditForm;
import com.yjb.tenet.boot.system.domain.query.SysUserPageQuery;
import com.yjb.tenet.boot.system.infrastructure.enums.FlagEnums;
import com.yjb.tenet.boot.system.infrastructure.enums.SysDeptRootEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yinjinbiao
 * @version 1.0
 * @description
 * @create 2022/4/18 10:50
 */
@Component
public class SysUserManager {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysRoleService sysRoleService;

	@Resource
	private SysDeptService sysDeptService;

    @Resource
    private SysUserChecker sysUserChecker;


    /**
     * 分页查询用户信息，附加角色信息
     *
     * @param page
     * @param param
     * @return
     */
    public IPage<SysUserPageDTO> page(Page<SysUserPageDTO> page, SysUserPageQuery param) {
        IPage<SysUserPageDTO> result = sysUserService.page(page, param);
        // 查询结果，添加角色信息
        result.getRecords().forEach(sysUserPageDTO -> {
            List<SysRolePageDTO> list = sysRoleService.listByUserId(sysUserPageDTO.getId());
            sysUserPageDTO.setRoles(list);
        });
        return result;
    }

    /**
     * 新增用户
     *
     * @param sysUserAddForm
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean save(SysUserAddForm sysUserAddForm) {
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(sysUserAddForm, sysUser);
        // 设置默认密码
        sysUser.setPassword(SecureUtil.md5("123456"));
        sysUserService.save(sysUser);
        // 设置角色
        List<SysUserRole> list = new ArrayList<>();
        sysUserAddForm.getRoles().forEach(roleId -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(sysUser.getId());
            sysUserRole.setRoleId(roleId);
            list.add(sysUserRole);
        });
        return sysUserRoleService.saveBatch(list);
    }

    /**
     * 编辑用户
     *
     * @param sysUserEditForm
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean edit(SysUserEditForm sysUserEditForm) {
        SysUser one = sysUserService.getById(sysUserEditForm.getId());
        BeanUtils.copyProperties(sysUserEditForm, one);
        sysUserService.updateById(one);
        // 设置角色
        // 先删除已设置的角色
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, sysUserEditForm.getId()));
        // 设置角色
        List<SysUserRole> list = new ArrayList<>();
        sysUserEditForm.getRoles().forEach(roleId -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(sysUserEditForm.getId());
            sysUserRole.setRoleId(roleId);
            list.add(sysUserRole);
        });
        return sysUserRoleService.saveBatch(list);

    }

    /**
     * 删除
     */
    public boolean delete(Long id) {
        SysUser sysUser = sysUserChecker.checkForOperate(id);
        sysUser.setDeleted(id);
        return sysUserService.updateById(sysUser);
    }

    /**
     * 重置密码
     *
     * @param id
     * @return
     */
    public boolean reset(Long id) {
        SysUser one = sysUserService.getById(id);
        one.setPassword(SecureUtil.md5("123456"));
        return sysUserService.updateById(one);
    }

    /**
     * 校验账号是否存在
     *
     * @param username
     * @return
     */
    public CheckMsg checkUsername(String username) {
        CheckMsg msg = new CheckMsg();
        SysUser one = sysUserService.lambdaQuery().eq(SysUser::getDeleted, GlobalConstants.NOT_DELETED)
                .eq(SysUser::getUsername, username)
                .one();
        if (ObjectUtil.isNull(one)) {
            msg.setPass(true);
        }
        return msg;
    }

    /**
     * 编辑个人信息
     *
     * @param myInfoEditForm
     * @return
     */
    public boolean editMyInfo(MyInfoEditForm myInfoEditForm) {
	    LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
	    SysUser sysUser = sysUserService.getById(loginUser.getId());
        // 验证密码是否正确
        boolean matches = SecureUtil.md5(myInfoEditForm.getPassword()).equals(sysUser.getPassword());
	    if (!matches) {
            throw new CustomException(ErrorCodeEnum.BUSINESS_FAIL.getCode(), "密码验证错误");
        }
        sysUser.setNickname(myInfoEditForm.getNickname());
        sysUser.setSex(myInfoEditForm.getSex());
        sysUser.setMobile(myInfoEditForm.getMobile());
        sysUser.setEmail(myInfoEditForm.getEmail());
        if (StrUtil.isNotBlank(myInfoEditForm.getNewPassword())) {
            sysUser.setPassword(SecureUtil.md5(myInfoEditForm.getNewPassword()));
        }
        return sysUserService.updateById(sysUser);
    }

    /**
     * 获取当前用户详细信息
     */
    public LoginUserDTO getMyInfo() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        LoginUserDTO loginUserDTO = new LoginUserDTO();
        loginUserDTO.setId(loginUser.getId());
        loginUserDTO.setUsername(loginUser.getUsername());
        SysUser sysUser = sysUserService.getById(loginUser.getId());
        loginUserDTO.setNickname(sysUser.getNickname());
        loginUserDTO.setPermissionCodes(loginUser.getPermissionCodes());
        loginUserDTO.setRoleCodes(loginUser.getRoleCodes());
        return loginUserDTO;
    }

	/**
	 * 完整部门树
	 */
	public List<Tree<Long>> deptUserTree() {
		List<SysDept> sysDepts = sysDeptService.lambdaQuery()
				.eq(SysDept::getDeleted, GlobalConstants.NOT_DELETED)
				.orderByAsc(SysDept::getOrderNo)
				.list();
		List<SysUser> sysUsers = sysUserService.lambdaQuery().eq(SysUser::getDeleted, GlobalConstants.NOT_DELETED).list();
		List<TreeNode<Long>> deptNodeList = sysDepts.stream().map(getDeptNodeFunction()).collect(Collectors.toList());
		List<TreeNode<Long>> userNodeList = sysUsers.stream().map(getUserNodeFunction()).collect(Collectors.toList());
		deptNodeList.addAll(userNodeList);
		return TreeUtil.build(deptNodeList, SysDeptRootEnum.ROOT.getValue());
	}

	@NotNull
	private Function<SysDept, TreeNode<Long>> getDeptNodeFunction() {
		return sysDept -> {
			TreeNode<Long> node = new TreeNode<>();
			node.setId(sysDept.getDeptId());
			node.setName(sysDept.getDeptName());
			node.setParentId(sysDept.getParentId());
			// 扩展属性
			Map<String, Object> extra = new HashMap<>();
			extra.put("isUser", FlagEnums.NO.getValue());
			node.setExtra(extra);
			return node;
		};
	}

	@NotNull
	private Function<SysUser, TreeNode<Long>> getUserNodeFunction() {
		return sysUser -> {
			TreeNode<Long> node = new TreeNode<>();
			node.setId(sysUser.getId());
			node.setName(sysUser.getNickname());
			node.setParentId(sysUser.getDeptId());
			// 扩展属性
			Map<String, Object> extra = new HashMap<>();
			extra.put("isUser", FlagEnums.YES.getValue());
			node.setExtra(extra);
			return node;
		};
	}
}
